#include <Channel.h>
#include <EventLoop.h>

Channel::Channel(EventLoop *loop, int fd)
    : loop_(loop),
      fd_(fd),
      event_(0),
      revent_(0),
      index_(-1),
      eventHandling_(false),
      addedToLoop_(false)
{
}

Channel::~Channel()
{
    assert(!eventHandling_);
    assert(!addedToLoop_);
    if (loop_->isInLoopThread())
    {
        assert(!loop_->hasChannel(this));
    }
}

void Channel::handleEvent()
{
    eventHandleWithGuard();
}

void Channel::eventHandleWithGuard()
{
    eventHandling_ = true;
    if (revent_ & EPOLLERR) // 出现异常
    {
        handleError();
    }
    if (!(revent_ & EPOLLIN) && revent_ & EPOLLHUP) // 对端正常关闭连接
    {
        handleClose();
    }
    if (revent_ & (EPOLLIN | EPOLLPRI)) // 处理读事件
    {
        handleRead();
    }
    if (revent_ & EPOLLOUT) // 处理写事件
    {
        handleWrite();
    }
    eventHandling_ = false;
}

std::string Channel::getReventMsg()
{
    std::string msg;
    if (revent_ | EPOLLIN)
    {
        msg += "EPOLLIN";
    }
    if (revent_ | EPOLLOUT)
    {
        msg += "EPOLLOUT";
    }
    if (revent_ | EPOLLERR)
    {
        msg += "EPOLLERR";
    }
    if (revent_ | EPOLLHUP)
    {
        msg += "EPOLLHUP";
    }
    return msg.size() == 0 ? "None Event" : msg;
}

std::string Channel::getEventMsg()
{
    std::string msg;
    if (revent_ | EPOLLIN)
    {
        msg += "EPOLLIN ";
    }
    if (revent_ | EPOLLOUT)
    {
        msg += "EPOLLOUT ";
    }
    if (revent_ | EPOLLERR)
    {
        msg += "EPOLLERR ";
    }
    if (revent_ | EPOLLHUP)
    {
        msg += "EPOLLHUP ";
    }
    return msg.size() == 0 ? "None Event" : msg;
}

void Channel::remove()
{
    assert(isNoneEvent());
    addedToLoop_ = false;
    loop_->removeChannel(this);
}

void Channel::tie(const std::shared_ptr<void> &ptr)
{
    tie_ = ptr;
    tied_ = true;
}

void Channel::update()
{
    addedToLoop_ = true;
    loop_->updateChannel(this);
}

void Channel::handleRead()
{
    assert(readCallback_);
    readCallback_();
}

void Channel::handleWrite()
{
    assert(writeCallback_);
    writeCallback_();
}

void Channel::handleError()
{
    assert(errorCallback_);
    errorCallback_();
}

void Channel::handleClose()
{
    assert(closeCallback_);
    closeCallback_();
}
